#include "MarketMenu.h"
#include "Utilities.h"
#include "PrintUtilities.h"
#include "UserManager.h"
#include "Team.h"
#include "AuctionManager.h"
#include "ServiceProvider.h"
#include "MenuManager.h"
#include "Player.h"
#include "GamePrintUtils.h"

#include <algorithm>

namespace
{
	void PrintMarketPlayerTitle(std::ostream& o_stream)
	{
		//todo...
		o_stream << Print::TabUpTo(" ", 4);
		o_stream << Print::TabUpTo("NAME", Player::GetPlayerParams().MAX_CHAR_PLAYER_NAME);
		PrintPlayerHeader(o_stream);
	}

	void PrintMarketPlayerData(std::ostream& o_stream, const Player& i_player)
	{
		//todo...
		PrintPlayer(o_stream, i_player, NUM_ROLES);
	}

	void PrintMarketPlayerDataLine(std::ostream& o_stream, const Player& i_player, const int i_index)
	{
		static const std::string bracket = ")";
		o_stream << i_index << Print::TabUpTo(bracket, (i_index>9 ? 2 : 3));
		PrintMarketPlayerData(o_stream, i_player);
	}
}

MarketMenu::MarketMenu(MenuManager* const i_menuManager)
	: Menu(i_menuManager)
{
}

void MarketMenu::Draw() const
{
	using std::cout;
	using std::endl;

	const UsersList& users = GetSP()->GetUserMgr().GetUserList();
	const Team& team = *(users[m_userIndex]->m_team);

	cout << Print::Title(" MARKET:");
	PrintTeam(cout, team);

	cout << Print::SeparatorLine();
	cout << "AVAILABLE PLAYERS ON MARKET:" << endl << endl;
	PrintMarketPlayerTitle(cout);

	unsigned int i = 0;
	const PlayerVec& marketPlayers = GetSP()->GetAuctionMgr().GetMarket();
	for(PlayerVecCit It = marketPlayers.begin(); It != marketPlayers.end(); ++It)
		PrintMarketPlayerDataLine(cout, *(*It), ++i);
	cout << endl;

	switch(m_status)
	{
	case BROWSING:

		if (m_error)
			cout << endl << m_errorMsg << endl << endl;

		cout	<< Print::Options(	"1) Goto edit formation.\n"
									"2) Buy player.\n"
									"3) Sell player.\n\n"
									"0) Return to previous menu'.")
				<<	"Selection: ";
		break;

	case BUYING:
		cout << "Select player to buy: ";
		break;

	case SELLING:
		cout << "Select player to sell: ";
		break;

	case BETTING:
		cout << "Insert your bet: \n";
		break;
	}
}


bool MarketMenu::Input(const std::string& i_input)
{
	bool goodInput = true;

	int res = Utilities::StringToInt(i_input);

	const UsersList& users = GetSP()->GetUserMgr().GetUserList();
	Team* team =  users[m_userIndex]->m_team;

	AuctionManager& AM = GetSP()->GetAuctionMgr();
	const PlayerVec& market = AM.GetMarket();

	m_error = false;
	m_errorMsg = "";

	switch(m_status)
	{
	case BROWSING:
		if (res == 0)
			GetMM()->SetMenu(GetMM()->GetTeamsManagementMenu());
		else if (res == 1)
			GetMM()->SetMenu(GetMM()->GetEditFormationMenu());
		else if (res == 2)
			if (market.empty()) 
			{
				m_errorMsg = "ERROR: No available players to buy!";
				m_error = true;
			}
			else if (team->GetNumPlayers() >= Team::GetParams().MAX_TEAM_PLAYERS)
				{
					m_errorMsg = "ERROR: Max team players number reached!!!!";
					m_error = true;
				}
			else
				m_status = BUYING;

		else if (res == 3)
			if (team->GetNumPlayers() > Team::GetParams().MIN_TEAM_PLAYERS)
				m_status = SELLING;
			else
			{
				m_error = true;
				m_errorMsg = "\n\nERROR: Min team players number reached!!!!\n\n";
			}
		else
			goodInput = false;
		break;

	case BUYING:
		if (res <= 0 || res > static_cast<int>(market.size()))
			return false;
		else
		{
			m_playerToBuy = res - 1;
			m_status = BETTING;
		}
		break;

	case BETTING:
		{
		Player* player = market.at(m_playerToBuy);
		size_t money = res;
		if(!GetSP()->GetAuctionMgr().Bidding(AuctionManager::Bet(team, player, money)))
		{
			m_errorMsg = "ERROR: You can't buy this player!";
			m_error = true;
		}
		m_status = BROWSING;
		}
		break;

	case SELLING:
		{
			if (res < 1 || res > static_cast<int>(team->GetNumPlayers()))
				return false;
			else
			{
				Player* player = team->GetPlayersList().at(res - 1);
				team->SellPlayer(player);
				m_status = BROWSING;
			}
		}
		break;
	}

	return goodInput;
}